package com.boot.generate;

import com.boot.generate.convert.TypeImplConvert;
import com.boot.generate.dto.TableDTO;
import com.boot.generate.mysql.SqlQuery;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import com.boot.generate.dto.ColumnDTO;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 通过模板自动生成相应代码
 *
 * @author 【zhouJie】
 */
public class VelocityGenerateCode {

    public static List<String> getTemplates() {
        List<String> templates = new ArrayList();
        templates.add("templates/Entity.java.vm");
        templates.add("templates/Dao.java.vm");
        templates.add("templates/Dao.xml.vm");
        templates.add("templates/Service.java.vm");
        templates.add("templates/ServiceImpl.java.vm");
        templates.add("templates/Controller.java.vm");
        return templates;
    }

    public static String tableToJava(String tableName, String tablePrefix) {
        if (StringUtils.isNotBlank(tablePrefix)) {
            tableName = tableName.replace(tablePrefix, "");
        }
        return columnToJava(tableName);
    }

    public static String columnToJava(String columnName) {
        columnName.replace("is_" , "");
        return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_" , "");
    }

    private static TableDTO getTableEntity(Object o) {
        try {
            Method method;
            if (o instanceof Map) {
                method = o.getClass().getMethod("get" , String.class);
            } else {
                method = o.getClass().getMethod("getString" , String.class);
            }
            String tableName = (String) method.invoke(o, SqlQuery.tableName());
            String tableComment = (String) method.invoke(o, SqlQuery.tableComment());
            TableDTO tableEntity = new TableDTO();
            tableEntity.setTableName(tableName);
            tableEntity.setComments(tableComment);
            String className = tableToJava(tableEntity.getTableName(), "");
            tableEntity.setClassName(className);
            tableEntity.setClassname(StringUtils.uncapitalize(className));
            return tableEntity;
        } catch (NoSuchMethodException var6) {
            var6.printStackTrace();
        } catch (IllegalAccessException var7) {
            var7.printStackTrace();
        } catch (InvocationTargetException var8) {
            var8.printStackTrace();
        }
        return null;
    }

    public static String getFileName(String template, String className, String packageName) {
        String packagePath = "main" + File.separator + "java" + File.separator;
        if (StringUtils.isNotBlank(packageName)) {
            packagePath = packagePath + packageName.replace("." , File.separator) + File.separator;
        }
        if (template.contains("Entity.java.vm")) {
            return packagePath + "entity" + File.separator + className + ".java";
        } else if (template.contains("Dao.java.vm")) {
            return packagePath + "dao" + File.separator + className + "Dao.java";
        } else if (template.contains("Dao.xml.vm")) {
            return packagePath + "mappers" + File.separator + className + ".xml";
        } else if (template.contains("Service.java.vm")) {
            return packagePath + "service" + File.separator + className + "Service.java";
        } else if (template.contains("ServiceImpl.java.vm")) {
            return packagePath + "serviceImpl" + File.separator + className + "ServiceImpl.java";
        } else if (template.contains("Controller.java.vm")) {
            return packagePath + "controller" + File.separator + className + "Controller.java";
        } else {
            return null;
        }
    }

    private static ColumnDTO getColumnEntity(Object o, TableDTO tableEntity) {
        try {
            Method method;
            if (o instanceof Map) {
                method = o.getClass().getMethod("get" , String.class);
            } else {
                method = o.getClass().getMethod("getString" , String.class);
            }
            ColumnDTO columnEntity = new ColumnDTO();
            columnEntity.setColumnName((String) method.invoke(o, SqlQuery.fieldName()));
            columnEntity.setDataType((String) method.invoke(o, SqlQuery.fieldType()));
            columnEntity.setComments((String) method.invoke(o, SqlQuery.fieldComment()));
            String attrName = columnToJava(columnEntity.getColumnName());
            columnEntity.setAttrName(attrName);
            columnEntity.setAttrname(StringUtils.uncapitalize(attrName));
            String attrType = (new TypeImplConvert()).processTypeConvert(columnEntity.getDataType()).getType();
            columnEntity.setAttrType(attrType);
            if (SqlQuery.isKeyIdentity((String) method.invoke(o, SqlQuery.fieldKey())) && tableEntity.getPk() == null) {
                tableEntity.setPk(columnEntity);
            }
            return columnEntity;
        } catch (NoSuchMethodException var6) {
            var6.printStackTrace();
        } catch (IllegalAccessException var7) {
            var7.printStackTrace();
        } catch (InvocationTargetException var8) {
            var8.printStackTrace();
        }
        return null;
    }

    private static void write(TableDTO tableEntity, ZipOutputStream zip, String packages) {
        Properties prop = new Properties();
        prop.put("file.resource.loader.class" , "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        Velocity.init(prop);
        Map<String, Object> map = new HashMap();
        map.put("tableName" , tableEntity.getTableName());
        map.put("comments" , tableEntity.getComments());
        map.put("pk" , tableEntity.getPk());
        map.put("className" , tableEntity.getClassName());
        map.put("classname" , tableEntity.getClassname());
        map.put("pathName" , tableEntity.getClassname());
        map.put("columns" , tableEntity.getColumns());
        map.put("package" , packages);
        map.put("author" , "【zhouJie】");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        map.put("datetime" , sdf.format(new Date()));
        VelocityContext context = new VelocityContext(map);
        List<String> templates = getTemplates();
        Iterator var7 = templates.iterator();
        while (var7.hasNext()) {
            String template = (String) var7.next();
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, "UTF-8");
            tpl.merge(context, sw);
            try {
                zip.putNextEntry(new ZipEntry(getFileName(template, tableEntity.getClassName(), packages)));
                IOUtils.write(sw.toString(), zip, "UTF-8");
                IOUtils.closeQuietly(sw);
                zip.closeEntry();
            } catch (IOException var12) {
                throw new RuntimeException("渲染模板失败，表名：" + tableEntity.getTableName(), var12);
            }
        }

    }

    private static Connection conn;

    private static Connection getConn(String url, String dataBaseName, String userName, String password) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://" + url + ":3306/" + dataBaseName + "?characterEncoding=utf8&useSSL=false" , userName, password);
        } catch (ClassNotFoundException var4) {
            var4.printStackTrace();
        } catch (SQLException var5) {
            var5.printStackTrace();
        }
        return conn;
    }

    public static void directGeneratorCode(String url, String dataBaseName, String userName, String password, String tableName, String packages) throws IOException, SQLException {
        File file = new File("");
        String filePath = file.getCanonicalPath();
        File file1 = new File(filePath);
        String filePath1 = file1.getParent();
        File file11 = new File(filePath1);
        String filePath11 = file11.getParent();
        File file2 = new File(filePath11 + "\\zhp_generate");
        if (!file2.exists()) {
            file2.mkdir();
        }
        String filePath2 = file2.getCanonicalPath();
        File file3 = new File(filePath2 + "\\code.zip");
        if (!file3.exists()) {
            file3.createNewFile();
        }
        FileOutputStream outputStream = new FileOutputStream(file3);
        Connection connection = getConn(url, dataBaseName, userName, password);
        String tablesSql;
        if (tableName == null || tableName.equals("")) {
            tablesSql = SqlQuery.tablesSql();
        } else {
            tablesSql = SqlQuery.tableSql(tableName);
        }
        ResultSet resultSet = connection.prepareStatement(tablesSql).executeQuery();
        ArrayList tableEntities = new ArrayList();
        while (resultSet.next()) {
            TableDTO tableEntity = getTableEntity(resultSet);
            tableEntities.add(tableEntity);
        }
        Iterator var13 = tableEntities.iterator();
        while (var13.hasNext()) {
            TableDTO te = (TableDTO) var13.next();
            ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
            String columnSql = SqlQuery.tableFieldsSql(te.getTableName());
            ResultSet rs = connection.prepareStatement(columnSql).executeQuery();
            ArrayList columns = new ArrayList();
            while (rs.next()) {
                columns.add(getColumnEntity(rs, te));
            }
            te.setColumns(columns);
            write(te, zipOutputStream, packages);
        }
    }

    public static void main(String[] args) throws IOException, SQLException {
        directGeneratorCode(
                "rm-2zermdu60n40y39q66o.mysql.rds.aliyuncs.com" ,
                "ceshi" ,
                "root123" ,
                "Bee1234%" ,
                "collage_total_voucher" ,
                "com.boot.web"
        );
//        int s = 1000;
//        for(int i=0;i<s;i++){
//            int iRandom = 1 + (int)(Math.random()*(9 + 1 - 1));
//            System.out.println(iRandom);
//        }
    }

}
